import java.net.*;
import java.io.*;

/**
 * @author Dennis Thomasen(whooper) & Nikolas Bram(Bram)
 * @studentId 20103903 				& 20104278 
 * @group 3
 * 
 */

public class Server {
	
	protected int port = 40303;
	protected ServerSocket serverSocket; 
		
	// Find servers IP-address
	public void findLocalHost(){
		try {
			InetAddress localhost = InetAddress.getLocalHost();
			String localhostAddress = localhost.getHostAddress();
			System.out.println("[SERVER]> Server IP-address: "+ localhostAddress);
		} catch (UnknownHostException e) {
			System.err.println("[SERVER]> Cannot resolve the Internet address of the local host.");
			System.err.println(e);
			System.exit(-1);
		}
	}
	
	// The server will be bind to a given port
	public void bindToPort(){
		try {
			serverSocket = new ServerSocket(port);
			System.out.println("[SERVER]> Server port: "+ port);
		} catch (IOException e) {
			serverSocket = null;
			System.err.println("[SERVER]> Cannot open server socket on port number" + port);
			System.err.println(e);
			System.exit(-1);			
		}	
	}
	
	// Waiting for connection from client
	public Socket waitForConnection(){
		Socket socket = null;
		try{
			socket = serverSocket.accept();
		} catch(IOException e){}
		return socket;		
	}


	// Run on server startup
	public void run(){
		System.out.println("[SERVER]> Connecting...");
		
		findLocalHost();
		bindToPort();
		
		while(true){
			Socket socket = waitForConnection();
			if(socket != null){
				RequestThread requestThread = new RequestThread(socket);
				requestThread.start();
			}
		}
	}
	
	// inner class - thread handling
	public class RequestThread extends Thread{
		 private Socket socket;
		 
		 public RequestThread (Socket socket) {
				this.socket = socket;
		 }
		 
		 public void run() {
			 System.out.println("[SERVER]> Request from: " + socket);
			 try {
				 BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				 DataOutputStream output = new DataOutputStream(socket.getOutputStream());
				 
				 httpHandler(input, output);
				 
				 output.close();
				 input.close();
				 socket.close();
			 } catch (IOException e) {
				 System.out.println(e);
			 }
		 }	 
	}
	
	// Making the header
	public String makeHeader(String filename, int responseCode){
		String header = null;
		header += "HTTP/1.0 ";
		
		switch(responseCode){
		case 200: 
				header += "200 OK"; break;
		case 404: 
				header += "404 Not Found"; break;
		}
		header += "\r\n";
		
		if(filename.endsWith(".jpg") || filename.endsWith(".jpeg")){
			header += "Content-Type: image/jpeg\r\n";
		}else if(filename.endsWith(".gif")){
			header += "Content-Type: image/gif\r\n";
		}else if(filename.endsWith(".txt")){
			header += "Content-Type: text/plain\r\n";
		}else if(filename.endsWith(".pdf")){
			header += "Contet-Type: application/pdf\r\n";
		}else{
			header += "Contet-Type: text/html\r\n";
		} 
		header += "\r\n";
		return header;		
	}
	
	// Handling the input from client
	public void httpHandler(BufferedReader input, DataOutputStream output) throws IOException{
		String request = input.readLine();
		if(request != null){
			int requestPart = request.indexOf(" ");
			String filename = request.substring(request.indexOf("/"), request.indexOf(" ", requestPart+1));
			
			System.out.println("[SERVER]> File requested: |"+ filename +"|");
			
			if(filename.equals("/")){
				filename = "index.html";
			}
			
			if(filename.indexOf("?") != -1){
				// |/shell-script.sh?INPUT=Test&sendtext=|
				
			} else {
				InputStream requestFileInput;
				int responseCode;
				
				try{
					File requestedFile = new File("FilesToBeServed/"+filename);
					requestFileInput = new FileInputStream(requestedFile);
					responseCode = 200;
				} catch(FileNotFoundException e){
					File requestedFile = new File("404.html");
					requestFileInput = new FileInputStream(requestedFile);
					responseCode = 404;
				}
				
				
				
				// Header sent to client
				output.writeBytes(makeHeader(filename, responseCode));
				
				// Content sent to client
				while(true){
					int bit = requestFileInput.read();
					if(bit == -1)
						break;
					output.write(bit);
				}
				System.out.println("[SERVER]> Response sent to Client");	
			}
		}
	}
	
	// Main method
	public static void main(String[] args) throws IOException {
		Server server = new Server();
		server.run();
	}
}